/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import net.worlds.object.GameObject;
import org.jbox2d.common.Vec2D;

/**
 *
 * @author Jacob Morgan
 */
public class ObjectList {
    private static HashMap<String, ObjectDef> objectDefs = new HashMap<String, ObjectDef>(WorldsSettings.MAX_TYPES);
    private static ArrayList<PropertyDef> globalProps = new ArrayList<PropertyDef>(WorldsSettings.MAX_PROPERTIES);
    private static HashMap<String, PropertyDef> propDefs = new HashMap<String, PropertyDef>(WorldsSettings.MAX_PROPERTIES);
    private static ArrayList<Class> objectClasses = new ArrayList<Class>(WorldsSettings.MAX_TYPES);
    public static void init() throws WorldsException
    {
        try
        {
            URL url = Main.class.getResource("/objects.txt");
            InputStream fi = url.openConnection().getInputStream();
            BufferedReader r = new BufferedReader(new InputStreamReader(fi));
            String l;
            while((l = r.readLine()) != null)
            {
                String[] params = l.split(" ");
                String cmd = params[0];
                if(cmd.equals("addglobalprop"))
                {
                    PropertyDef d = new PropertyDef();
                    d.name = params[1];
                    d.type = Class.forName(params[2]);
                    propDefs.put(d.name, d);
                    d.guiEditable = Boolean.parseBoolean(params[3]);
                    d.scriptEditable = Boolean.parseBoolean(params[4]);
                    d.defaultValue = parseValue(d.type, params[5]);
                    d.classification = PropertyDef.CLASS_BOTH;
                    globalProps.add(d);
                }
                else if(cmd.equals("addobject"))
                {
                    ObjectDef d = new ObjectDef();
                    d.name = params[1];
                    if(params.length == 3)
                        d.visible = Boolean.parseBoolean(params[2]);
                    else
                        d.visible = true;
                    try
                    {
                        AssetManager.loadImage(d.name, "resource://objects/"+d.name+".png");
                    }
                    catch(Exception ex){}
                    for(PropertyDef pd : globalProps)
                    {
                        d.properties.add(pd);
                    }
                    objectDefs.put(d.name, d);
                    Class c = Class.forName("net.worlds.object."+params[1]);
                    objectClasses.add(c);
                }
                else if(cmd.equals("addprop") || cmd.equals("addhprop") || cmd.equals("addxprop"))
                {
                    PropertyDef d = new PropertyDef();
                    d.name = params[2];
                    d.type = Class.forName(params[3]);
                    propDefs.put(d.name, d);
                    d.guiEditable = Boolean.parseBoolean(params[4]);
                    d.scriptEditable = Boolean.parseBoolean(params[5]);
                    d.defaultValue = parseValue(d.type, params[6]);
                    //System.err.println(params[1]+" "+objectDefs.get(params[1]));
                    if(cmd.equals("addhprop"))
                        d.classification = 2;
                    else if(cmd.equals("addxprop"))
                        d.classification = 1;
                    else
                        d.classification = 0;
                    objectDefs.get(params[1]).properties.add(d);
                }
            }
        }
        catch(Exception ex)
        {
            if(ex instanceof WorldsException)
                throw (WorldsException) ex;
            else
            {
                Main.error(ex, true);
            }
        }
    }
    public static boolean isDefault(String name, Object value)
    {
        for(PropertyDef p : globalProps)
        {
            if(p.name.equals(name) && p.defaultValue != null && p.defaultValue.equals(value))
                return true;
        }
        for(String k : propDefs.keySet())
        {
            if(k.equals(name) && propDefs.get(k).defaultValue != null && propDefs.get(k).defaultValue.equals(value))
                return true;
        }
        return false;
    }
    public static PropertyDef getPropDef(String type, String name)
    {
        ArrayList<PropertyDef> props = objectDefs.get(type).properties;
        for(PropertyDef d : props)
        {
            if(d.name.equals(name))
                return d;
        }
        Main.log("Unknown property: "+type+" "+name);
        return null;
    }
    public static Object parseValue(Class type, String s) throws WorldsException
    {
        try
        {
            if(type == String.class)
            {
                if(s.equals("X"))
                    s = "";
                return s;
            }
            else if(type == Integer.class)
            {
                return Integer.parseInt(s);
            }
            else if(type == Boolean.class)
            {
                return Boolean.parseBoolean(s);
            }
            else if(type == Float.class)
            {
                return Float.parseFloat(s);
            }
            else if(type == Vec2D.class)
            {
                return Vec2D.fromString(s);
            }
            else if(type == Color.class)
            {
                return Util.colorFromString(s);
            }
            else if(type == GameObject.class)
            {
                return null;
            }
            throw new WorldsException("Invalid property type "+type.getSimpleName());
        }
        catch(Exception ex)
        {
            if(ex instanceof WorldsException)
                throw (WorldsException) ex;
            else
                throw new WorldsException("Error parsing value: "+type+" "+s);
        }
    }
    public static ObjectDef getDef(String type)
    {
        return objectDefs.get(type);
    }
    public static ArrayList<Class> getAllClasses()
    {
        return objectClasses;
    }
}
